#include "instructions/constants/ldc.hpp"
#include "rtda/frame.h"
#include <stdexcept>
#include <variant>

namespace jvm {
namespace instructions {

void Ldc::Execute(Frame& frame) {
    detail::ExecuteLdc(frame, index_);
}

void LdcW::Execute(Frame& frame) {
    detail::ExecuteLdc(frame, index_);
}

void Ldc2W::Execute(Frame& frame) {
    auto stack = frame.getOperandStack();
    auto cp = frame.getMethod()->getClass()->getConstantPool();
    auto constant = cp->getConstant(index_);

    // 使用 std::visit 和 std::variant 处理不同类型
    std::visit(
        [stack](auto&& arg) {
            using T = std::decay_t<decltype(arg)>;
            if constexpr (std::is_same_v<T, int64_t>) {
                stack->pushLong(arg);
            } else if constexpr (std::is_same_v<T, double>) {
                stack->pushDouble(arg);
            } else {
                throw std::runtime_error("java.lang.ClassFormatError");
            }
        },
        constant
    );
}

namespace detail {

void ExecuteLdc(Frame& frame, uint16_t index) {
    auto stack = frame.getOperandStack();
    auto cp = frame.getMethod()->getClass()->getConstantPool();
    auto constant = cp->getConstant(index);

    // 使用 std::visit 和 std::variant 处理不同类型
    std::visit(
        [stack](auto&& arg) {
            using T = std::decay_t<decltype(arg)>;
            if constexpr (std::is_same_v<T, int32_t>) {
                stack->pushInt(arg);
            } else if constexpr (std::is_same_v<T, float>) {
                stack->pushFloat(arg);
            } else {
                // TODO: 处理 string, ClassRef, MethodType, MethodHandle 等情况
                throw std::runtime_error("todo: ldc!");
            }
        },
        constant
    );
}

} // namespace detail

} // namespace instructions
} // namespace jvm